const { Builder, By, until } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const firefox = require('selenium-webdriver/firefox');
const fs = require('fs');

/**
 * 版本2：使用 Selenium WebDriver 动态爬取评论数据
 * 这个版本直接对应 Python 的 Selenium 方法
 * 可以成功获取动态加载的评论数据
 */

class CourseReviewScraper {
    constructor(browser = 'chrome') {
        this.driver = null;
        this.allReviews = [];
        this.browserType = browser;
    }

    // 初始化浏览器
    async init() {
        console.log(`正在启动 ${this.browserType} 浏览器...`);

        try {
            if (this.browserType === 'firefox') {
                // 使用 Firefox（相当于 Python 的 webdriver.Firefox()）
                const firefoxOptions = new firefox.Options();
                firefoxOptions.windowSize({ width: 1082, height: 672 });
                // firefoxOptions.headless(); // 如果需要无头模式

                this.driver = await new Builder()
                    .forBrowser('firefox')
                    .setFirefoxOptions(firefoxOptions)
                    .build();
            } else {
                // 默认使用 Chrome（相当于 Python 的 webdriver.Chrome()）
                const chromeOptions = new chrome.Options();
                chromeOptions.windowSize({ width: 1082, height: 672 });
                // chromeOptions.headless(); // 如果需要无头模式
                chromeOptions.addArguments('--disable-blink-features=AutomationControlled');
                chromeOptions.excludeSwitches(['enable-automation']);

                this.driver = await new Builder()
                    .forBrowser('chrome')
                    .setChromeOptions(chromeOptions)
                    .build();
            }

            console.log('浏览器启动成功！');
        } catch (error) {
            console.error('浏览器启动失败:', error.message);
            console.log('\n请确保：');
            console.log('1. 已安装对应的浏览器（Chrome 或 Firefox）');
            console.log('2. 已下载对应的 WebDriver：');
            console.log('   - ChromeDriver: https://chromedriver.chromium.org/');
            console.log('   - GeckoDriver: https://github.com/mozilla/geckodriver/releases');
            console.log('3. WebDriver 已添加到系统 PATH 中');
            throw error;
        }
    }

    // 打开页面并点击评论按钮
    async openPageAndClickReview() {
        const url = "https://www.icourse163.org/course/NHDX-1463126169";

        console.log(`正在访问: ${url}`);
        await this.driver.get(url);

        // 等待页面加载
        await this.driver.sleep(3000);

        try {
            console.log('等待评论按钮加载...');

            // 等待按钮出现并可点击（相当于 Python 的 WebDriverWait）
            const reviewButton = await this.driver.wait(
                until.elementLocated(By.id('review-tag-button')),
                10000
            );

            // 确保按钮可见
            await this.driver.wait(until.elementIsVisible(reviewButton), 5000);

            console.log('点击评论按钮...');
            await reviewButton.click();

            // 等待评论内容加载
            await this.driver.sleep(3000);

            // 等待评论列表出现
            await this.driver.wait(
                until.elementLocated(By.css('.ux-mooc-comment-course-comment_comment-list_item')),
                10000
            );

            console.log('评论内容已加载！');

        } catch (error) {
            console.error('无法点击课程评价按钮:', error.message);
        }
    }

    // 提取当前页面的评论
    async extractReviews() {
        console.log('正在提取评论数据...');

        try {
            // 查找所有评论元素（相当于 Python 的 find_elements）
            const reviewElements = await this.driver.findElements(
                By.css('.ux-mooc-comment-course-comment_comment-list_item')
            );

            console.log(`找到 ${reviewElements.length} 条评论`);

            // 遍历每个评论元素
            for (let element of reviewElements) {
                try {
                    const review = {};

                    // 提取用户名
                    try {
                        const userElement = await element.findElement(
                            By.css('.ux-mooc-comment-course-comment_comment-list_item_body_user-info_name')
                        );
                        review.user = await userElement.getText();
                    } catch (e) {
                        review.user = '';
                    }

                    // 提取评论时间
                    try {
                        const timeElement = await element.findElement(
                            By.css('.ux-mooc-comment-course-comment_comment-list_item_body_comment-info_time')
                        );
                        review.time = await timeElement.getText();
                    } catch (e) {
                        review.time = '';
                    }

                    // 提取评分（星星数）
                    try {
                        const stars = await element.findElements(
                            By.css('.ux-icon-custom-rating-favorite')
                        );
                        review.rating = stars.length;
                    } catch (e) {
                        review.rating = 0;
                    }

                    // 提取评论内容
                    try {
                        const contentElement = await element.findElement(
                            By.css('.ux-mooc-comment-course-comment_comment-list_item_body_content')
                        );
                        review.content = await contentElement.getText();
                    } catch (e) {
                        review.content = '';
                    }

                    this.allReviews.push(review);
                } catch (error) {
                    console.error('解析单条评论时出错:', error.message);
                }
            }

            console.log(`本页成功提取 ${reviewElements.length} 条评论`);

        } catch (error) {
            console.error('提取评论时出错:', error.message);
        }
    }

    // 点击下一页
    async nextPage() {
        try {
            // 查找下一页按钮
            const nextButtonSelector = '.ux-pager_btn.ux-pager_btn__next a';
            const nextButtons = await this.driver.findElements(By.css(nextButtonSelector));

            if (nextButtons.length === 0) {
                return false;
            }

            const nextButton = nextButtons[0];

            // 检查按钮是否被禁用
            const parentElement = await this.driver.executeScript(
                'return arguments[0].parentElement;',
                nextButton
            );
            const className = await parentElement.getAttribute('class');

            if (className && className.includes('ux-pager_btn__disabled')) {
                console.log('下一页按钮已禁用');
                return false;
            }

            console.log('点击下一页...');

            // 滚动到按钮位置
            await this.driver.executeScript('arguments[0].scrollIntoView(true);', nextButton);
            await this.driver.sleep(500);

            // 点击按钮
            await nextButton.click();
            await this.driver.sleep(3000);  // 等待页面加载

            return true;
        } catch (error) {
            console.log('无法点击下一页:', error.message);
            return false;
        }
    }

    // 主爬取函数
    async scrape(numPages = 5) {
        await this.init();
        await this.openPageAndClickReview();

        // 提取指定页数的评论
        for (let page = 1; page <= numPages; page++) {
            console.log(`\n正在提取第 ${page} 页的评论...`);
            await this.extractReviews();

            // 如果不是最后一页，尝试翻页
            if (page < numPages) {
                const hasNext = await this.nextPage();
                if (!hasNext) {
                    console.log('已到达最后一页，停止翻页。');
                    break;
                }
            }
        }

        // 保存数据
        await this.saveData();

        // 关闭浏览器
        await this.close();
    }

    // 保存数据为CSV格式
    async saveData() {
        if (this.allReviews.length === 0) {
            console.log('没有评论数据可保存');
            return;
        }

        // 创建CSV内容
        const headers = ['user', 'time', 'rating', 'content'];
        const csvContent = [
            headers.join(','),
            ...this.allReviews.map(review => {
                return [
                    `"${(review.user || '').replace(/"/g, '""')}"`,
                    `"${(review.time || '').replace(/"/g, '""')}"`,
                    review.rating || 0,
                    `"${(review.content || '').replace(/"/g, '""').replace(/\n/g, ' ')}"`
                ].join(',');
            })
        ].join('\n');

        // 保存为CSV文件
        const outputFile = `course_reviews_selenium_${this.browserType}.csv`;
        fs.writeFileSync(outputFile, '\ufeff' + csvContent, 'utf-8');  // \ufeff 是 UTF-8 BOM
        console.log(`\n数据已保存到 ${outputFile}`);
        console.log(`共保存 ${this.allReviews.length} 条评论`);

        // 同时保存为JSON格式
        const jsonFile = `course_reviews_selenium_${this.browserType}.json`;
        fs.writeFileSync(jsonFile, JSON.stringify(this.allReviews, null, 2), 'utf-8');
        console.log(`JSON数据已保存到 ${jsonFile}`);
    }

    // 关闭浏览器
    async close() {
        if (this.driver) {
            await this.driver.quit();
            console.log('\n所有页面处理完毕，浏览器已关闭');
        }
    }
}

// 执行爬虫
async function main() {
    // 可以选择使用 Chrome 或 Firefox
    const scraper = new CourseReviewScraper('chrome');  // 使用 Chrome
    // const scraper = new CourseReviewScraper('firefox');    // 使用 Firefox

    try {
        // 爬取5页评论
        await scraper.scrape(5);
    } catch (error) {
        console.error('爬取过程中出错:', error);
        await scraper.close();
    }
}

// 运行主函数
main();